<template>
  <view class="chatPage">
    <view class="top">
      <span class="back" @click="back">
        <image src="../../static/images/common/back.png" mode=""></image>
      </span>
      <span class="title">{{info.name}}</span>
      <view class="right" v-if="info.type == 1" @click="goutoGroup">
        <image :src="info.favater" mode=""></image>
      </view>
    </view>

    <view class="main">
      <scroll-view class="chat-body" scroll-y="true" :scroll-with-animation="info.animation"
        :scroll-into-view="info.scrollTo" @scrolltoupper="nextPage">
        <view class="list" :style="{ paddingBottom: info.inputh + 'px' }">
          <view class="loading" :class="{ displaynode: info.isLoading }">
            <image src="../../static/images/common/loading.png" class="loading-img" mode=""
              :animation="info.animationData">
            </image>
          </view>
          <view class="chat-list" v-for="(item, index) in info.messageList" :key="index" :id="'msg' + index">
            <view class="chat-time" v-if="item.time != ''">
              <span>{{ formatTime(item.time) }}</span>
            </view>
            <view class="msg-m" :class="item.userid == userInfo.userid  ? 'msg-right' : 'msg-left'">
              <image :src="item.imgurl" mode="" @click="gotoAddFriend(item)"></image>
              <view class="message" :class="item.userid == userInfo.userid ? 'right' : 'left'" v-if="item.types == 0">
                <span>{{ item.message }}</span>
              </view>
              <!-- 图片 -->
              <view class="message msg-img" :class="item.userid == userInfo.userid ? 'right' : 'left'"
                v-if="item.types == 1">
                <image @click="showImg(item.message)" :src="item.message" mode=""></image>
              </view>
              <!-- 音频 -->
              <view class="message" :class="item.userid == userInfo.userid ? 'right' : 'left'" v-if="item.types == 2">
                <view class="voice le" v-if="item.userid !=userInfo.userid" :style="{width:item.message.time*8 +'rpx' }"
                  @click="playAudio(item.message.voice)">
                  <image src="../../static/images/chartroom/ly.png" mode=""></image>
                  <span>{{item.message.time}}″</span>
                </view>
                <view class="voice ri" v-if="item.userid == userInfo.userid"
                  :style="{width:item.message.time*8 +'rpx' }" @click="playAudio(item.message.voice)">
                  <span>{{item.message.time}}″</span>
                  <image src="../../static/images/chartroom/ly.png" mode=""></image>
                </view>
              </view>

              <!-- 位置 -->
              <view :class="item.userid == userInfo.userid ? 'right' : 'left'" v-if="item.types == 3">
                <view class="msg-map" @click="openLocation(item.message)">
                  <view class="msg-name">{{item.message.name}}</view>
                  <view class="msg-address">{{item.message.address}}</view>
                  <image src="../../static/images/chartroom/map.png" mode="aspectFill"></image>
                </view>
              </view>

            </view>
          </view>
        </view>
      </scroll-view>
    </view>
    <chatBox></chatBox>
  </view>
</template>

<script setup>
  import chatBox from '@/components/chatBox/chatBox.vue'
  import {
    reactive,
    onMounted,
    nextTick,
    getCurrentInstance,
  } from 'vue';
  import {
    formatTime
  } from '@/utils/formatDate'
  import {
    useStore
  } from '@/store/index'
  import {
    onLoad,
    onShow
  } from '@dcloudio/uni-app'
  import mitter from '@/utils/mitt';
  // import _ from 'lodash'
  import {
    debounce
  } from '@/utils/utils.js'
  import {
    useUserStore
  } from '@/store/user.js'
  import {
    requestNet
  } from '@/api/base.js'
  import {
    fileName
  } from '@/utils/formatDate.js'
  const instance = getCurrentInstance()
  //使用仓库
  const store = useStore()
  const user = useUserStore() //创建仓库
  const info = reactive({
    id: null, //跳转进来的好友id || 群id
    name: '', //好友名字 || 群名字
    favater: '', //好友头像
    type: null, //判断是群还是个人对话
    messageList: [], //聊天消息列表
    imglist: [], //图片列表
    oldTime: 0, //当前时间
    inputh: 5.5, //底部padding值
    flag: 1,
    scrollTo: '', //滚动子元素的id
    innerAudioContext: uni.createInnerAudioContext(), //保存每次获取音频的实例
    animationData: {},
    currentPage: 0, //当前页
    timer: null, //loading的定时器
    isLoading: true, //是否显示loading
    animation: true, //控制滚动动画
    pageSize: 10, //分页 每页显示条数
  })
  //当前登录用户信息
  const userInfo = reactive({
    userid: null, //当前登录用户id
    avater: '', //当前登录用户头像  
    token: '', //登录验证
    uname: '', //当前登录用户名
  })

  function getChat() {
    if (info.type == 0) {
      getChatBy()
    } else if (info.type == 1) {
      getGroupMsg()
    }
  }

  //获取聊天数据 一对一
  function getChatBy(page = 1) {
    requestNet({
      url: '/chat/getmsg',
      data: {
        uid: userInfo.userid,
        id: info.id,
        pageSize: info.pageSize,
        curPage: page
      },
      header: {
        token: userInfo.token
      }
    }).then(res => {
      // console.log(res)
      let code = res.data.code
      if (code == 200) {
        let set = new Set()
        let msg = res.data.data
        msg.reverse()
        if (msg.length > 0) {
          let oldtime = msg[0].time
          msg[0].imgurl = instance.proxy.serverUrl + msg[0].imgurl
          for (let i = 1; i < msg.length; i++) {
            msg[i].imgurl = instance.proxy.serverUrl + msg[i].imgurl
            if (i < msg.length) { //最后一个时间不做此处理
              let t = spaceTime(oldtime, msg[i].time)
              if (t) {
                //把t置换为返回的发送消息的时间
                oldtime = t
              }
              msg[i].time = t
            }
            //从数据库中取出图片数据进行处理
            if (msg[i].types == 1) {
              msg[i].message = instance.proxy.serverUrl + msg[i].message
              set.add(msg[i].message)
            }
            //从数据库中还原地图字符串为js对象
            if (msg[i].types == 3) {
              msg[i].message = JSON.parse(msg[i].message)
            }
          }
          //现在取的数组拼接上之前取的数组
          info.messageList = msg.concat(info.messageList)
        }
        //限制不会超过message数组的长度
        if (msg.length == 10) {
          info.currentPage++
        } else {
          // 数据获取完毕
          info.currentPage = -1
        }

        let temp = [...set]
        for (let i = 0; i < temp.length; i++) {
          info.imglist.unshift(temp[i])
        }
        nextTick(() => {
          info.animation = false
          info.scrollTo = `msg${msg.length - 1 }`
        })
        //清除计时器
        info.isLoading = true //隐藏loading
      }

    }).catch(err => {
      uni.showToast({
        title: err,
        icon: 'error'
      })
    })
  }

  //获取群聊天数据
  function getGroupMsg(page = 1) {
    requestNet({
      url: '/chat/getgroupmsg',
      data: {
        gid: info.id,
        pageSize: info.pageSize,
        curPage: page
      },
      header: {
        token: userInfo.token
      }
    }).then(res => {
      let code = res.data.code
      if (code == 200) {
        let set = new Set()
        let msg = res.data.data
        msg.reverse()
        if (msg.length > 0) {
          let oldtime = msg[0].time
          msg[0].imgurl = instance.proxy.serverUrl + msg[0].imgurl
          for (let i = 1; i < msg.length; i++) {
            msg[i].imgurl = instance.proxy.serverUrl + msg[i].imgurl
            if (i < msg.length) { //最后一个时间不做此处理
              let t = spaceTime(oldtime, msg[i].time)
              if (t) {
                //把t置换为返回的发送消息的时间
                oldtime = t
              }
              msg[i].time = t
            }
            //从数据库中取出图片数据进行处理
            if (msg[i].types == 1) {
              msg[i].message = instance.proxy.serverUrl + msg[i].message
              set.add(msg[i].message)
            }
            //从数据库中还原地图字符串为js对象
            if (msg[i].types == 3) {
              msg[i].message = JSON.parse(msg[i].message)
            }
          }
          //现在取的数组拼接上之前取的数组
          info.messageList = msg.concat(info.messageList)
        }
        //限制不会超过message数组的长度
        if (msg.length == 10) {
          info.currentPage++
        } else {
          // 数据获取完毕
          info.currentPage = -1
        }

        let temp = [...set]
        for (let i = 0; i < temp.length; i++) {
          info.imglist.unshift(temp[i])
        }
        nextTick(() => {
          info.animation = false
          info.scrollTo = `msg${msg.length - 1 }`
        })
        //清除计时器
        info.isLoading = true //隐藏loading
      }

    }).catch(err => {
      uni.showToast({
        title: err,
        icon: 'error'
      })
    })
  }

  //loading动画加载函数  上拉获取
  function nextPage() {
    if (info.currentPage > 0) {
      info.isLoading = false //展示loading
      let animation = uni.createAnimation({
        duration: 1000,
        timingFunction: 'step-start',
      })
      //动画过程
      let i = 1;
      info.timer = setInterval(function() {
        //每过0.1s，i++，旋转角度加大30°
        animation.rotate(i * 30).step()
        info.animationData = animation.export()
        i++
        console.log(i)
        //加上防抖操作  //再次获取聊天数据   1秒内不能多次触发getChatBy方法
        debounce(getChatBy(info.currentPage), 3000)

      }.bind(this), 100)
    } else {
      uni.showToast({
        title: '没有数据啦~',
        icon: 'error'
      })
      return;
    }
  }

  //获取缓存数据
  function getStorage() {
    if (Object.keys(user.userinfo).length != 0) { //如果有数据，登录过了
      userInfo.userid = user.userinfo.userid
      userInfo.avater = user.userinfo.imgurl
      userInfo.token = user.token
      userInfo.uname = user.userinfo.username
      if (!user.userinfo.imgurl.includes(instance.proxy.serverUrl)) { //不包含服务器地址
        userInfo.avater = `${instance.proxy.serverUrl}${user.userinfo.imgurl}`
      }
    } else { //否则跳转到登录页面
      uni.navigateTo({
        url: '/pages/login/login'
      })
    }
  }

  //间隔时间差
  function spaceTime(old, now) {
    old = new Date(old)
    now = new Date(now)
    let told = old.getTime()
    let tnow = now.getTime()
    if (tnow > (told + 1000 * 60 * 5)) { //当前时间发送消息时间比大于五分钟
      return now //返回发送消息的时间
    } else return ''
  }

  function back() {
    //告知离开当前聊天页面
    instance.proxy.socket.emit('leaveChat', userInfo.userid, info.id, info.type)
    //使上一个页面不需重新加载
    uni.navigateBack({
      delta: 1
    })
    //摧毁当前音频实例
    info.innerAudioContext.destroy()
  }

  function showImg(item) {
    let str = item.split('/')
    let picName = str[str.length - 1].split('.')[0];
    let index = null
    info.imglist.forEach((ele, i) => {
      // console.log(ele);
      if (ele.indexOf(picName) !== -1) {
        index = i
        return
      }
    })
    uni.previewImage({
      urls: info.imglist,
      current: index,
      indicator: 'number'
    })
  }

  //接收聊天信息
  function getMessage(data) {
    dealMsg(data, userInfo.userid, userInfo.avater, 0)
  }

  //处理聊天信息
  function dealMsg(obj, fromId, img, type) { //先提交给后端,在渲染
    console.log('处理聊天信息')
    //type=0表示自己发的，type=1表示别人发的
    //socket提交给后端  
    if (obj.types == 0 || obj.types == 3) { //如果是文本内容
      sendSocket(obj)
    }
    if (obj.types == 1) { //如果是图片
      info.imglist.push(obj.message)
      let url = fileName(new Date()) //当天日期文件夹
      //实现多张图片逐一上传 至服务器  
      const uploadTask = uni.uploadFile({
        url: `${instance.proxy.serverUrl}/files/upload`, //仅为示例，非真实的接口地址[后端接口地址]
        filePath: obj.message,
        name: 'file',
        formData: {
          url: url,
          name: new Date().getTime().toString() + userInfo.userid + Math.ceil(Math.random() * 10)
        },
        success: (uploadFileRes) => {
          console.log(uploadFileRes);
          let data = {
            message: uploadFileRes.data,
            types: 1
          }
          sendSocket(data)
        }
      });
    }
    //音频
    if (obj.types == 2) {
      let url = fileName(new Date()) //当天日期文件夹
      //实现多张图片逐一上传 至服务器  
      const uploadTask = uni.uploadFile({
        url: `${instance.proxy.serverUrl}/files/upload`, //仅为示例，非真实的接口地址[后端接口地址]
        filePath: obj.message.voice,
        name: 'file',
        formData: {
          url: url,
          name: new Date().getTime().toString() + userInfo.userid + Math.ceil(Math.random() * 10)
        },
        success: (uploadFileRes) => {
          console.log(uploadFileRes);
          let data = {
            message: uploadFileRes,
            types: e.types
          }
          sendSocket(data)
        }
      });
    }

    let len = info.messageList.length
    let nowTime = new Date()
    // 时间间隔判断
    let t = spaceTime(info.oldTime, nowTime)
    if (t) {
      info.oldTime = t
    }
    nowTime = t
    if (obj.types == 3) {
      //还原为js对象
      obj.message = JSON.parse(obj.message)
    }
    let data = {
      "userid": fromId,
      "imgurl": img,
      "message": obj.message,
      "types": obj.types,
      "time": nowTime,
      //"tip": len
    }
    info.messageList.push(data)

    srcollDown()
  }

  mitter.on('getMsg', getMessage)

  //聊天数据发送给后端
  function sendSocket(e) {
    if (info.type == 0) {
      //1对1聊天
      instance.proxy.socket.emit('Msg', e, userInfo.userid, info.id);
    } else {
      //群聊天
      instance.proxy.socket.emit('groupMsg', e, userInfo.userid, info.id, userInfo.uname, userInfo.avater);
    }
  }

  //socket聊天数据接收 一对一
  function receiveSocketMsg() {
    instance.proxy.socket.on('msg', (msg, fromid, flag) => {
      console.log('一对一后端发送的消息是', msg, fromid, flag)
      if (fromid == info.id && flag == 0) { //接收方判断，如果是与点击进入的好友用户id一致
        let nowTime = new Date()
        // 时间间隔判断
        let t = spaceTime(info.oldTime, nowTime)
        if (t) {
          info.oldTime = t
        }
        nowTime = t
        if (msg.types == 1 || msg.types == 2) {
          msg.message = instance.proxy.serverUrl + msg.message
        }
        if (msg.types == 3) {
          //还原为js对象
          msg.message = JSON.parse(msg.message)
        }
        let data = {
          "userid": fromid,
          "imgurl": info.favater,
          "message": msg.message,
          "types": msg.types,
          "time": nowTime,
        }
        info.messageList.push(data)
        if (msg.types == 1) {
          info.imglist.push(msg.message)
        }
        //定位到最后一条消息的位置
        srcollDown()
      }
    })
  }

  //socket聊天数据接收 群
  function groupSocketMsg() {
    instance.proxy.socket.on('groupmsg', (msg, fromid, gid, name, img, flag) => {
      console.log('群后端发送的消息是', msg, fromid, flag)
      if (gid == info.id && flag == 0) { //接收方判断，如果是与点击进入的群id一致
        let nowTime = new Date()
        // 时间间隔判断
        let t = spaceTime(info.oldTime, nowTime)
        if (t) {
          info.oldTime = t
        }
        nowTime = t
        if (msg.types == 1 || msg.types == 2) {
          msg.message = instance.proxy.serverUrl + msg.message
        }
        if (msg.types == 3) {
          //还原为js对象
          msg.message = JSON.parse(msg.message)
        }
        let data = {
          "userid": fromid,
          "imgurl": img,
          "message": msg.message,
          "types": msg.types,
          "time": nowTime,
        }
        info.messageList.push(data)
        if (msg.types == 1) {
          info.imglist.push(msg.message)
        }
        //定位到最后一条消息的位置
        srcollDown()
      }
    })
  }


  function srcollDown() {
    let len = info.messageList.length
    info.animation = true
    info.scrollTo = ''
    nextTick(() => {
      info.scrollTo = `msg${len-1}`
    })
  }

  //接收聊天页面底部弹出层高度
  function dealBottomHeight(height) {
    info.inputh = height
    srcollDown()
  }
  //全局事件总线
  mitter.on('dealHeight', dealBottomHeight)

  // 播放音频
  function playAudio(e) {
    //创建音频对象
    info.innerAudioContext = uni.createInnerAudioContext();
    info.innerAudioContext.autoplay = true;
    info.innerAudioContext.src = e
    info.innerAudioContext.volume = 1
    info.innerAudioContext.onPlay(() => {
      console.log('开始播放');
    });
  }

  onLoad((e) => {
    info.id = parseInt(e.id)
    info.name = e.name
    info.favater = e.img
    info.type = parseInt(e.type)
    getStorage() //获取缓存数据
    // getChatBy(1) //获取聊天数据
    getChat()
    receiveSocketMsg()
    groupSocketMsg()
  })

  onShow(() => {

  })

  //进入群详情
  function goutoGroup() {
    uni.navigateTo({
      url: `/pages/grouphome/grouphome?uid=${userInfo.userid}&gid=${info.id}&img=${info.favater}`
    })
  }

  //跳转到用户主页
  function gotoAddFriend(item) {
    console.log(item)
    uni.navigateTo({
      url: `/pages/reqfirend/reqfirend?id=${item.userid}`
    })
  }

  //点击地图，进入具体位置
  function openLocation(e) {
    uni.openLocation({
      latitude: e.latitude,
      longitude: e.longitude,
      name: e.name,
      address: e.address,
      success: function() {
        console.log('success');
      }
    });
  }
</script>

<style lang="scss" scoped>
  @import '@/assets/css/top.scss';

  .chatPage {
    background-color: #efefef;

    .top {
      padding: 0 20rpx;
      display: flex;
      align-items: center;
      height: 88rpx;
      border-bottom: 2rpx solid var(--border-color);
      background: var(--bg-color-grey);
      position: fixed;

      .back {
        display: inline-block;
        height: 40rpx;
        width: 40rpx;

        image {
          height: 90%;
          width: 90%;
        }
      }

      .title {
        position: absolute;
        //居中显示
        transform: translateX(-50%);
        left: 50%;
        font-size: 36rpx;
      }

      .right {
        width: 68rpx;
        height: 68rpx;

        image {
          width: 100%;
          height: 100%;
        }
      }
    }

    .main {
      padding-top: 95rpx;
      // padding-bottom: 15rpx;
      height: calc(100vh - 95rpx);
      // height: 100%;
    }

    .chat-body {
      height: 100%;
      padding: 0 20rpx;
      // padding-bottom: 20rpx;

      .loading {
        text-align: center;

        &-img {
          width: 60rpx;
          height: 60rpx;
        }
      }

      .chat-list {
        margin-bottom: 20rpx;

        .chat-time {
          font-size: 24rpx;
          color: var(--text-color-grey);
          padding: 20rpx 0;
          text-align: center;
        }

        .msg-left {
          display: flex;


          .left {
            margin-left: 20rpx;
            background: var(--bg-color);
            border-radius: 0 20rpx 20rpx;
          }
        }

        .msg-right {
          display: flex;
          flex-direction: row-reverse;
          margin-bottom: 20rpx;

          .right {
            margin-right: 20rpx;
            border-radius: 20rpx 0 20rpx;
            background: #89d961;
          }
        }

        .msg-img {
          background: none !important;
          width: 300rpx;
          height: 300rpx;

          image {
            height: 100%;
            width: 100%;
          }
        }
      }
    }

    .test {
      width: 100%;
    }
  }

  .msg-map {
    background: #fff;
    width: 464rpx;
    height: 284rpx;
    overflow: hidden;
    border-radius: 20rpx 0 20rpx;

    .msg-name {
      padding: 20rpx 0 5rpx 20rpx;
      font-size: 30rpx;
      color: black;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 1;
      overflow: hidden;
    }

    .msg-address {
      font-size: 25rpx;
      color: #959595;
      padding-left: 20rpx;
      padding-bottom: 8rpx;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 1;
      overflow: hidden;
    }

    image {
      width: 464rpx;
      height: 176rpx;
    }
  }

  uni-map {
    width: 464rpx;
    height: 176rpx;
  }

  .message {
    max-width: 480rpx;
    min-width: 100rpx;
    padding: 20rpx;
  }

  image {
    border-radius: 20rpx;
    width: 80rpx;
    height: 80rpx;
  }

  .voice {
    min-width: 80rpx;
    max-width: 400rpx;

    image {
      width: 35rpx;
      height: 35rpx;
      margin: 0 10rpx;
    }
  }

  .ri {
    display: flex;
    align-items: center;
    justify-content: flex-end;
  }

  .le {
    display: flex;
    align-items: center;
    justify-content: flex-start;

    image {
      transform: rotate(180deg);
    }
  }

  .displaynode {
    display: none;
  }
</style>
